﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;

namespace Steve.UI.Extensions
{
    [Export(typeof(ICacheService))]
    public sealed class MemoryCacheService : ICacheService
    {
        static Dictionary<CacheType, Dictionary<string, Tuple<DateTime?, object>>> _cache = new Dictionary<CacheType, Dictionary<string, Tuple<DateTime?, object>>>();

        public T GetValue<T>(CacheType cacheType, string cacheKey) where T : class
        {
            Dictionary<string, Tuple<DateTime?, object>> inner;

            if (!_cache.TryGetValue(cacheType, out inner) || inner == null) return null;

            Tuple<DateTime?, object> value;

            if (!inner.TryGetValue(cacheKey, out value)) return null;

            //expired
            if (value.Item1 != null && value.Item1 < DateTime.Now) return null;

            return (T) value.Item2;
        }

        public void PutValue(CacheType cacheType, string cacheKey, object value, TimeSpan? ttl)
        {
            Dictionary<string, Tuple<DateTime?, object>> inner;

            if (!_cache.TryGetValue(cacheType, out inner) || inner == null)
            {
                inner = new Dictionary<string, Tuple<DateTime?, object>>();
                _cache[cacheType] = inner;
            }

            inner[cacheKey] = Tuple.Create(ttl == null ? (DateTime?)null : DateTime.Now + ttl.Value, value);
        }

        public void Invalidate(CacheType cacheType, string cacheKey)
        {
            Dictionary<string, Tuple<DateTime?, object>> inner;

            if (!_cache.TryGetValue(cacheType, out inner) || inner == null) return;

            if (inner.ContainsKey(cacheKey)) inner.Remove(cacheKey);
        }

        public void Invalidate(CacheType cacheType)
        {
            if (_cache.ContainsKey(cacheType)) _cache.Remove(cacheType);
        }

        public IEnumerable<string> GetKeys(CacheType cacheType)
        {
            Dictionary<string, Tuple<DateTime?, object>> inner;

            if (!_cache.TryGetValue(cacheType, out inner) || inner == null) return new string[] {};

            return inner.Keys;
        }
    }
}
